
#include "app.h"
#include "exceptions.h"
#include "clog.h"
#include "sdl_rotozoom.h"

#define MN_TITLE_OFF    130
#define MN_FIRST_OFF    90
#define MN_NEXT_OFF     40

#define FRAME_LIMIT     60

App::App()
{
	_screen = 0;
	_mode = MD_MENU;
	_menu_option = 0;
	_curr_menu_item = 0;
	test_angle = 0;
	mousex = 0;
	mousey = 0;
}

App::~App()
{
	//dtor
}

i32 App::RunThisShit()
{
	InitializeVideo ( 800, 600, 32 );
	LOGP1 ( "App initialized...[OK]" );
	SDL_Surface *text;
	u32 background = SDL_MapRGB ( _screen->format, 0x33, 0x33, 0x33 );
	SDL_FillRect ( _screen, 0, background );
	SDL_Rect dst;
	dst.w = 400;
	dst.h = 400;
	SDL_Color color;
	color.b = 255;
	color.g = 0;
	color.r = 0;
	text = TTF_RenderText_Solid ( cour_big, "Loading...", color );
	dst.x = _screen->w / 2 - text->w / 2;
	dst.y = _screen->h / 2 - text->h / 2;
	SDL_BlitSurface ( text, NULL, _screen, &dst );
	SDL_Flip ( _screen );
	Sleep ( 500 );
	RES->LoadLiveObject ( "data/etank.bmp", "enem2", 5 );
	RES->LoadStatic ( "data/life.bmp", "life" );
	RES->LoadLiveObject ( "data/tankp.bmp", "playa1", 1 );
	RES->LoadLiveObject ( "data/tankp.bmp", "playa2", 1 );
	RES->Load360Object("data/barrel.bmp","barrel");
	//LoadSprite ( "data/life.bmp", GO_LIFE );
//	LoadLiveObject ( "data/tank.bmp", GO_PLAYER1, 4 );
//	LoadSprite ( "data/tank2.bmp", GO_PLAYER2 );
	RES->LoadLiveObject ( "data/etank.bmp", "enem1", 5 );
	RES->LoadLiveObject ( "data/e2tank.bmp", "enem2", 5 );
	RES->LoadStatic ( "data/eagle.bmp", "eagle" );
	RES->LoadStatic ( "data/bullet.bmp", "bullet" );
	RES->LoadStatic ( "data/brick.bmp", "brick" );
	RES->LoadStatic ( "data/wall.bmp", "wall" );
	RES->LoadStatic ( "data/back.bmp", "back" );
	RES->LoadAnimFromSheet ( "data/explo.bmp", "explo", 0, 0, 32, 32, 3 );
	RES->LoadAnimFromSheet ( "data/born.bmp", "born", 0, 0, 32, 32, 6 );
	g_screen = _screen;
	_my_scene = new Scene();
	_my_scene->_screen = _screen;
	_my_scene->mousex = &mousex;
	_my_scene->mousey = &mousey;
	_my_scene->_big = cour_big;
	_my_scene->_med = cour_med;
	_my_scene->_sml = cour_sml;
	_my_scene->_sprites = &_sprites[0];
	_my_scene->SetupDefaultStage();
	//// <<<< TEST >>>>
	callbackV1 clb;
	clb.bind ( this, &App::test );
//	t_timer.doPeriodicaly(50,clb);
	t_timer.doPeriodicaly ( 250, clb );
	t_timer.start();
	DoEvents();
	CleanUp();
	return 1;
}

i32 App::InitializeVideo ( u32 w, u32 h, u32 bpp )
{
	if ( SDL_Init ( SDL_INIT_VIDEO ) < 0 )
	{
		LOGP2 ( "Couldn't init %s",  SDL_GetError() );
		EXCC ( 0x01 );
	}

	if ( TTF_Init() < 0 )
	{
		LOGP1 ( "Couldn't init TTF" );
		EXCC ( 0x03 );
	}

	cour_big = TTF_OpenFont ( "data/lucon.ttf", 40 );
	cour_med = TTF_OpenFont ( "data/bgothl.ttf", 26 );
	cour_sml = TTF_OpenFont ( "data/courier_new.ttf", 14 );
	TTF_SetFontStyle ( cour_sml, TTF_STYLE_BOLD );

	if ( !cour_big || !cour_med || !cour_sml )
	{
		LOGP1 ( "Couldn't load font" );
		EXCC ( 0x03 );
	}

	_screen = SDL_SetVideoMode ( w, h, bpp, SDL_SWSURFACE | SDL_ANYFORMAT );

	if ( ! _screen )
	{
		LOGP5 ( "Couldn't set video mode [%d x %d x %d bpp]: %s", w, h, bpp, SDL_GetError() );
		EXCC ( 0x02 );
	}

    g_fdebug = cour_sml;

	return 1;
}
i32 App::KeyInMenu ( SDL_Event &event )
{
	switch ( event.key.keysym.sym )
	{
		case SDLK_UP:
		{
			_menu_option--;
			break;
		}

		case SDLK_DOWN:
		{
			_menu_option++;
			break;
		}

		case SDLK_RETURN:
		{
			_mode = MD_GAME;
			break;
		}

		default:
		{
			break;
		}
	}

	if ( _menu_option > ( i32 ) _MENU_SIZE ) {
		_menu_option = 0;
	}

	if ( _menu_option < 0 ) {
		_menu_option = _MENU_SIZE;
	}

	return 1;
}

i32 App::KeyInGame ( )
{
    u8 *keystate = SDL_GetKeyState(0);


		if (keystate[SDLK_UP])
		{
            _my_scene->p1->Drive(1);
		}
		if (keystate[SDLK_DOWN])
		{
            _my_scene->p1->Drive(0);
		}
		if (keystate[SDLK_RIGHT])
		{
            _my_scene->p1->Rotate(1);
		}
		if (keystate[SDLK_LEFT])
		{
            _my_scene->p1->Rotate(0);
		}


	return 1;
}

i32 App::KeyPressed ( SDL_Event &event )
{
	if ( _mode == MD_GAME )
	{
//		KeyInGame ( event );
	}

	if ( _mode == MD_MENU )
	{
		KeyInMenu ( event );
	}

	return 1;
}

i32 App::DoEvents()
{
	u32 done = 0;
	SDL_Event event;
	u32 tnow = SDL_GetTicks();
	i32 ticks = 0;

	while ( !done )
	{
		ticks = SDL_GetTicks();

		while ( SDL_PollEvent ( &event ) )
		{
			switch ( event.type ) {
				case SDL_MOUSEMOTION:
				{
					//SDL_WarpMouse ( _screen->w / 2, _screen->h / 2 );
					mousex = event.motion.x;
					mousey = event.motion.y;
					break;
				}

				case SDL_KEYDOWN:
				{
					if ( event.key.keysym.sym == SDLK_ESCAPE )
					{
						done = 1;
						break;
					}

					KeyPressed ( event );
					break;
				}

				case SDL_QUIT:
				{
					done = 1;
					break;
				}

				default:
				{
					break;
				}
			}
		}
		// do shit here !
		if (_mode == MD_GAME)
            KeyInGame();
		Render();
		static i32 fps = 0;

		if ( SDL_GetTicks() >= tnow + 1000 )
		{
			char buff[100];
			sprintf ( buff, "FPS: %d", _frames );
			SDL_WM_SetCaption ( buff, 0 );
			fps = _frames;
			_frames = 0;
			tnow = SDL_GetTicks();
		}

		_frames++;
		ticks = SDL_GetTicks() - ticks;

		if ( ticks < 1000 / FRAME_LIMIT ) {
			SDL_Delay ( ( 1000 / FRAME_LIMIT ) - ticks );
		}

		Timer::checkAndRun();
	}

	return 1;
}

i32 App::Render()
{
	if ( _mode == MD_GAME ) {
		DrawScene();
	}

	if ( _mode == MD_MENU ) {
		DrawMainMenu();
	}

	return 1;
}

i32 App::CleanUp()
{
	if ( _my_scene ) {
		delete _my_scene;
	}

	SDL_Quit();
	return 1;
}

i32 App::LoadSprite ( string filename, u32 sprite_ID )
{
	SDL_Surface *temp;
	SDL_Surface *sprite = SDL_LoadBMP ( filename.c_str() );
	Sprite n_spr;

	if ( sprite == NULL )
	{
		LOGP2 ( "Error while loading %s", filename.c_str() );
		EXCEX ( 0x01, "Sprite loading failed !" );
		return ( -1 );
	}

	if ( sprite->format->palette )
	{
		SDL_SetColorKey ( sprite, ( SDL_SRCCOLORKEY | SDL_RLEACCEL ),
						  * ( Uint8 * ) sprite->pixels );
	}

	temp = SDL_DisplayFormat ( sprite );
	SDL_FreeSurface ( sprite );

	if ( temp == NULL )
	{
		LOGP3 ( "Couldn't convert background: %s [%s]", SDL_GetError(), filename.c_str() );
		EXCEX ( 0x01, "Sprite loading failed !" );
		return ( -1 );
	}

	Frame f;
	f.surface[0] = temp;
	n_spr.frames.push_back ( f );
	n_spr.ID = sprite_ID;
	_sprites.push_back ( n_spr );
	LOGP3 ( "Sprite [%s] : [%d] loaded...[OK]", filename.c_str(), sprite_ID );
	return 0;
}
//
//
//i32 App::LoadAnim ( string filename, u32 sprite_ID, u32 frames )
//{
//	SDL_Surface *temp;
//	SDL_Surface *sprite;
//	Sprite n_spr;
//
//	if ( frames > 16 )
//	{
//		EXCEX ( 0x05, "So many frames ? Are you out of youre mind ?" );
//	}
//
//	for ( u32 c = 0; c < frames; c++ )
//	{
//		char buff[100], buff2[100], ext[30];
//		u32 dot = filename.rfind ( "." );
//		memcpy ( buff, filename.c_str(), dot );
//		buff[dot] = 0;
//		memcpy ( ext, filename.c_str() + dot, filename.length() - dot );
//		ext[filename.length() - dot] = 0;
//		sprintf ( buff2, "%s%d%s", buff, c, ext );
//		//LOGP2("FILE %s",buff2);
//		sprite = SDL_LoadBMP ( buff2 );
//
//		if ( sprite == NULL )
//		{
//			LOGP2 ( "Error while loading %s", buff2 );
//			EXCEX ( 0x01, "Sprite loading failed !" );
//			return ( -1 );
//		}
//
//		if ( sprite->format->palette )
//		{
//			SDL_SetColorKey ( sprite, ( SDL_SRCCOLORKEY | SDL_RLEACCEL ),
//							  * ( Uint8 * ) sprite->pixels );
//		}
//
//		temp = SDL_DisplayFormat ( sprite );
//		SDL_FreeSurface ( sprite );
//
//		if ( temp == NULL )
//		{
//			LOGP3 ( "Couldn't convert background: %s [%s]", SDL_GetError(), buff2 );
//			EXCEX ( 0x01, "Sprite loading failed !" );
//			return ( -1 );
//		}
//
//		Frame f;
//		f.surface[0] = temp;
//		n_spr.frames.push_back ( f );
//		u32 *pix_data;
//
//		if ( temp->format->BytesPerPixel == 4 )
//		{
//			for ( i32 c = 0; c < temp->w * temp->h * 4; c += 4 )
//			{
//				pix_data = ( u32 * ) & ( ( u8 * ) temp->pixels ) [c];
//				*pix_data = *pix_data | 0xFF000000;
//			}
//		}
//
//		//255,   174,201
//
//		if ( c == 0 )
//		{
//			n_spr.w = temp->w;
//			n_spr.h = temp->h;
//		}
//		else
//		{
//			if ( ( n_spr.w != ( u32 ) temp->w ) || ( n_spr.h != ( u32 ) temp->h ) )
//			{
//				EXCEX ( 0x06, "Animation frames have defferent size." );
//			}
//		}
//
//		LOGP3 ( "Sprite [%s] : [%d] loaded...[OK]", buff2, sprite_ID );
//	}
//
//	n_spr.ID = sprite_ID;
//	_sprites.push_back ( n_spr );
//	return _sprites.size() - 1;     // number of currently added sprite
//}


i32 App::DrawScene()
{
	u32 background = SDL_MapRGB ( _screen->format, BGR_R, BGR_G, BGR_B );
	SDL_FillRect ( _screen, 0, background );
	_my_scene->DrawStage();
	SDL_Flip ( _screen );
	return 1;
}
//
//i32 App::LoadLiveObject ( string filename, u32 sprite_ID, u32 frames )
//{
//	LOGP2 ( "Loading game object [%s]...", filename.c_str() );
//	u32 v_id = LoadAnim ( filename, sprite_ID, frames );
//	LOGP3 ( "Loading animation completed [%d frames]. Rotating images...%d times", frames, ANGLES );
//	SDL_Surface *tmp = 0;
//
//	for ( u32 c = 0; c < frames; c++ )
//	{
//		for ( u32 v = 0; v < ANGLES; v++ )
//		{
//			double ang = 360 / ANGLES * v;
//			tmp = rotozoomSurface ( _sprites[v_id].frames[c].surface[0], ang, 1, 1 );
//			_sprites[v_id].frames[c].surface[v] = tmp;
//			u32 *pix_data;
//			u32 cl = 0x00FFAEC9;
//
//			if ( tmp->format->BytesPerPixel == 4 )
//			{
//				for ( u32 c = 0; c < ( u32 ) ( tmp->w * tmp->h * 4 ); c += 4 )
//				{
//					pix_data = ( u32 * ) & ( ( u8 * ) tmp->pixels ) [c];
//
//					if ( ( *pix_data & 0x00FFFFFF ) == cl ) {
//						*pix_data = 0x00000000;
//					}
//				}
//			}
//
//		}
//	}
//
//	return 1;
//}

i32 App::DrawMainMenu()
{
	SDL_Surface *text;
	u32 background = SDL_MapRGB ( _screen->format, 0xA3, 0xA3, 0xA3 );
	SDL_FillRect ( _screen, 0, background );
	SDL_Color color;
	color.b = 0x05;
	color.g = 0x10;
	color.r = 0xC0;
	SDL_Rect dst;
	dst.x = 0;
	dst.y = 0;
	dst.w = 800;
	dst.h = 600;
	Graphics *graph;
	graph = ( Graphics * ) RES->GET ( "back" );
	SDL_SetAlpha ( graph->spr.frames[0].surface[0], SDL_SRCALPHA, 0x50 );
	SDL_BlitSurface (  graph->spr.frames[0].surface[0], 0, _screen, &dst );
	text = TTF_RenderText_Blended ( cour_big, "Tank 1991", color );
	dst.x = _screen->w / 2 - text->w / 2;
	dst.y = MN_TITLE_OFF;
	SDL_BlitSurface ( text, NULL, _screen, &dst );
	SDL_FreeSurface ( text );
	_curr_menu_item = 0;
	_MENU_SIZE = 4;
	DrawNextMenuItem ( "Start game" );
	DrawNextMenuItem ( "Start server" );
	DrawNextMenuItem ( "Join Game" );
	DrawNextMenuItem ( "About" );
	DrawNextMenuItem ( "Quit" );
	SDL_Flip ( _screen );
	return 1;
}

i32 App::DrawNextMenuItem ( string txt )
{
	SDL_Rect dst;
	SDL_Surface *text;
	dst.w = 800;
	dst.h = 600;
	SDL_Color color;
	color.b = 40;
	color.g = 40;
	color.r = 40;

	if ( _menu_option != _curr_menu_item )
	{
		color.b = 29;
		color.g = 230;
		color.r = 180;
	}
	else
	{
		color.b = 40;
		color.g = 50;
		color.r = 245;
	}

	text = TTF_RenderText_Blended ( cour_med, txt.c_str(), color );
	dst.x = _screen->w / 2 - text->w / 2;
	dst.y = MN_TITLE_OFF + MN_FIRST_OFF + MN_NEXT_OFF * _curr_menu_item;
	SDL_BlitSurface ( text, NULL, _screen, &dst );
	SDL_FreeSurface ( text );
	_curr_menu_item++;
	return 1;
}




